package cn.kgc.tangcco.service.impl;

import cn.kgc.tangcco.dao.StudentDao;
import cn.kgc.tangcco.model.PageParam;
import cn.kgc.tangcco.model.ResponseText;
import cn.kgc.tangcco.model.ResultCode;
import cn.kgc.tangcco.pojo.Student;
import cn.kgc.tangcco.service.StudentService;
import cn.kgc.tangcco.utils.cryptography.BaseCryptographyUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * @author 李昊哲
 * @Description
 * @create 2021/1/12 14:44
 */
@Service
public class StudentServiceImpl implements StudentService {

    private final static String key = "lihaozhelihaozhelihaozhelihaozhelihaozhelihaozhelihaozhelihaozhe";

    @Autowired
    private StudentDao studentDao;


    @Override
    public ResponseText<Student> findOne(Integer id) {
        if (id == null) {
            return new ResponseText<>(ResultCode.PARAM_ERROR.getCode(), ResultCode.PARAM_ERROR.getMsg(), null);
        }
        Optional<Student> optional = studentDao.findById(id);
        if (optional.isEmpty()) {
            return new ResponseText<>(ResultCode.DATA_EMPTY.getCode(), ResultCode.DATA_EMPTY.getMsg(), null);
        }
        Student student = optional.get();
        student.setAuthText(BaseCryptographyUtils.desDecodeHexString(student.getAuthText(), key));
        return new ResponseText<>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), student);
    }

    @Override
    public ResponseText<Student> getOne(Integer id) {
        if (id == null) {
            return new ResponseText<>(ResultCode.PARAM_ERROR.getCode(), ResultCode.PARAM_ERROR.getMsg(), null);
        }
        try {
            Student student = studentDao.getOne(id);
            student.setAuthText(BaseCryptographyUtils.desDecodeHexString(student.getAuthText(), key));
            return new ResponseText<>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), student);
        } catch (Exception exception) {
            return new ResponseText<>(ResultCode.DATA_EMPTY.getCode(), ResultCode.DATA_EMPTY.getMsg(), null);
        }
    }

    @Override
    public ResponseText<Student> selectOne(Integer id) {
        if (id == null) {
            return new ResponseText<>(ResultCode.PARAM_ERROR.getCode(), ResultCode.PARAM_ERROR.getMsg(), null);
        }
        Student student = studentDao.selectOne(id);
        if (student == null) {
            return new ResponseText<>(ResultCode.DATA_EMPTY.getCode(), ResultCode.DATA_EMPTY.getMsg(), null);
        }
        student.setAuthText(BaseCryptographyUtils.desDecodeHexString(student.getAuthText(), key));
        return new ResponseText<>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), student);
    }

    @Override
    public ResponseText<List<Student>> findLike(String firstName) {
        if (StringUtils.isBlank(firstName)) {
            return new ResponseText<>(ResultCode.PARAM_ERROR.getCode(), ResultCode.PARAM_ERROR.getMsg(), new ArrayList<>());
        }
        StringBuilder param = new StringBuilder();
        param.append("%");
        param.append(firstName);
        param.append("%");
        List<Student> students = studentDao.findStudentLikeName(param.toString(), param.toString());
        if (students != null && students.size() > 0) {
            return new ResponseText<>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), students);
        }
        return new ResponseText<>(ResultCode.DATA_EMPTY.getCode(), ResultCode.DATA_EMPTY.getMsg(), new ArrayList<>());
    }

    @Transactional(rollbackFor = {Exception.class, RuntimeException.class}, propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
    @Override
    public ResponseText<Student> update(Student student) {
        if (student == null || student.getId() == null) {
            return new ResponseText<>(ResultCode.PARAM_ERROR.getCode(), ResultCode.PARAM_ERROR.getMsg(), null);
        }
        if (!studentDao.existsById(student.getId())) {
            return new ResponseText<>(ResultCode.PARAM_ERROR.getCode(), ResultCode.PARAM_ERROR.getMsg(), null);
        }
        String authText = BaseCryptographyUtils.desEncodeHexString(student.getAuthText(), key);
        int status = studentDao.update(student.getId(), student.getFirstName(), student.getLastName(), student.getIdCard(), student.getMobile(), authText, student.getCid());
        // System.out.println(1 / 0);
        if (status > 0) {
            return new ResponseText<>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), student);
        }
        return new ResponseText<>(ResultCode.FAILED.getCode(), ResultCode.FAILED.getMsg(), student);
    }

    @Override
    public ResponseText<List<Student>> nativeQuery(Student student) {
        if (student == null || student.getCid() == null || StringUtils.isBlank(student.getFirstName())) {
            return new ResponseText<>(ResultCode.PARAM_ERROR.getCode(), ResultCode.PARAM_ERROR.getMsg(), null);
        }
        StringBuilder nickname = new StringBuilder();
        nickname.append("%");
        nickname.append(student.getFirstName());
        nickname.append("%");
        List<Student> students = studentDao.nativeQuery(student.getCid(), nickname.toString(), nickname.toString());
        if (students != null && students.size() > 0) {
            return new ResponseText<>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), students);
        }
        return new ResponseText<>(ResultCode.DATA_EMPTY.getCode(), ResultCode.DATA_EMPTY.getMsg(), new ArrayList<>());
    }

    @Override
    public ResponseText<Student> loginByMobileAndAuthText(Student student) {
        if (student == null || StringUtils.isBlank(student.getMobile()) || StringUtils.isBlank(student.getAuthText())) {
            return new ResponseText<>(ResultCode.PARAM_ERROR.getCode(), ResultCode.PARAM_ERROR.getMsg(), null);
        }
        student.setAuthText(BaseCryptographyUtils.desEncodeHexString(student.getAuthText(), key));
        try {
            return new ResponseText<>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), studentDao.findOne((root, cq, cb) -> {
                return cb.and(cb.equal(root.get("mobile"), student.getMobile()), cb.equal(root.get("authText"), student.getAuthText()));
            }).get());
        } catch (Exception exception) {
            return new ResponseText<>(ResultCode.LOGIN_FAILED.getCode(), ResultCode.LOGIN_FAILED.getMsg(), null);
        }
    }

    @Override
    public ResponseText<List<Student>> specificationLike(String firstName) {
        if (StringUtils.isBlank(firstName)) {
            return new ResponseText<>(ResultCode.PARAM_ERROR.getCode(), ResultCode.PARAM_ERROR.getMsg(), new ArrayList<>());
        }
        List<Student> students = studentDao.findAll((root, cq, cb) -> {
            StringBuilder nickname = new StringBuilder();
            nickname.append("%");
            nickname.append(firstName);
            nickname.append("%");
            return cb.or(cb.like(root.get("firstName").as(String.class), nickname.toString()), cb.like(root.get("lastName").as(String.class), nickname.toString()));
        }, Sort.by(Sort.Direction.DESC, "cid"));
        if (students != null && students.size() > 0) {
            return new ResponseText<>(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMsg(), students);
        }
        return new ResponseText<>(ResultCode.DATA_EMPTY.getCode(), ResultCode.DATA_EMPTY.getMsg(), new ArrayList<>());
    }

    @Override
    public Page<Student> page(Student student, PageParam pageParam) {
        return studentDao.findAll((root, cq, cb) -> {
            Predicate cid = null;
            Predicate nickName = null;
            if (student.getCid() != null && student.getCid() > 0) {
                cid = cb.equal(root.get("cid"), student.getCid());
            }
            if (!StringUtils.isBlank(student.getFirstName())) {
                StringBuilder nickname = new StringBuilder();
                nickname.append("%");
                nickname.append(student.getFirstName());
                nickname.append("%");
                nickName = cb.or(cb.like(root.get("firstName").as(String.class), nickname.toString()), cb.like(root.get("lastName").as(String.class), nickname.toString()));
            }
            if (cid != null && nickName != null) {
                return cb.and(cid, nickName);
            } else if (cid != null && nickName == null) {
                return cid;
            } else if (cid == null && nickName != null) {
                return nickName;
            } else {
                return null;
            }
        }, PageRequest.of(pageParam.getPageNum() - 1, pageParam.getPageSize(), Sort.by(Sort.Direction.DESC, "id")));
    }

}
